TypeScript is a natural extension of JavaScript that’s used in many projects in place of JavaScript.
However, not everyone knows how it actually works.
In this article, we’ll look at how to work with objects and classes in TypeScript.
Merging Methods
If we have 2 object types that have the same method name, then TypeScript will try to create a function with the signature being an intersection of both.
For instance, if we have:
type Cat = {
name: string;
speak: (words: number) => string;
};
type Animal = {
name: string;
speak: (words: string) => string;
};
const person: Cat | Animal = {
name: "james",
speak(words) {
return words;
}
};
Then we can’t pass in anything into words
since words
would have the type number & string
which is an impossible intersection.
Therefore, it’s impossible to pass anything into the speak
method.
Constructor Functions
Objects can be created with constructor functions in JavaScript.
They can also be used with TypeScript code, but the way they are supported isn’t intuitive and not as elegant as the way classes are handled.
For instance, we can write:
function Person(name) {
this.name = name;
}
In JavaScript to create a constructor function.
In TypeScript, we would get an error for this
for having the implicit any
type if we have noImplicitAny
.
Therefore, we need a way to specify the type of this
if we have that set to true
.
For instance, we can write:
function Person(this: { name: string }, name: string) {
this.name = name;
}
The this
parameter must be the first parameter.
It won’t be in the built JavaScript code. The name
parameter will still be treated as the first parameter in the compiled JavaScript code.
Classes
TypeScript doesn’t have good support for constructor functions.
Its focus is on improving the class syntax.
The class syntax is good for people that are familiar with other programming languages to get acquainted with Typescript.
We’ve to declare instance properties and their types in TypeScrtipt classes.
This makes classes more verbose, but it allows the constructor parameter types to be different from the type of the instance properties to which they’re assigned.
Objects are created from classes using the new
keyword.
The compiler understands the use of the instanceof
keyword for narrowing classes.
For instance, we can write:
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
}
We have the instance variable declaration on top and we assign the value for it in the constructor.
Access Control Keywords
TypeScript provides access control keywords to control access to the object’s instance properties.
This is something that isn’t available in JavaScript.
There are 3 access control keywords.
public
allows free access to a property or method and it’s the default keyword.
private
restricts access to the class that defines the property or method it’s applied to.
protected
restricts access to the class that defines the property or method it’s applied to and its subclasses.
We add the access control keyword before the instance variable name:
class Person {
public name: string;
constructor(name: string) {
this.name = name;
}
}
The built JavaScript code won’t have these keywords, so we can’t rely on them to shield data from the outside.
Ensuring Instance Properties are Initialized
The strictPropertyInitialization
compiler option can be set to true
to ensure that all instance properties are initialized.
The strictNullCheck
option should be enabled for this to work.
Read-Only Properties
The readonly
keyword can be used to create instance properties where the value is assigned in the constructor only.
It can’t be assigned a value anywhere else.
For instance, we can write:
class Person {
public name: string;
readonly id: number;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
We added the readonly
keyword as we did with the access modifiers.
Simplifying Class Constructors
We can simplify class constructors by moving the instance variables into the constructor signature.
For instance, we can write:
class Person {
constructor(readonly id: number, public name: string) {}
}
That’s exactly the same as what we have in the previous example.
It’s just shorter.
So if we instantiate it as follows:
const person = new Person(1, "james");
We get the same result.
Conclusion
TypeScript will merge methods from class when we create an intersection type.
Also, TypeScript adds enhancements to the JavaScript class syntax to make everything clearer.